`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:  X-Speed.com.cn
// Engineer: yansf
// 
// Create Date:    01/16/2024
// Design Name: 
// Module Name:    StatusDet 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////

module StatusDet(
//-----------input clk
	Clk, 
	Clk_5ms,
//-----------input RESET signals
	nRst,
//-----------com1,com2 console mode det register
	Com1_Console_mode_det,
	Com2_Console_mode_det,
//-----------CHIP to FPGA mode DET signals
	RS485_422_RE0_DET_FPGA,
	RS485_DE0_ISO_DET_FPGA,
	RS232_TX_EN0_DET_FPGA,
	RS422_DE0_DET_FPGA,
	RS485_422_RE1_DET_FPGA,
	RS485_DE1_ISO_DET_FPGA,
	RS232_TX_EN1_DET_FPGA,
	RS422_DE1_DET_FPGA,
//-----------BYPASS voltage det to FPGA
	BP_VOL_OV, //over voltage
	BP_VOL_UV, //under voltage
	BP_VOLTAGE_DIODE_DET,
//-----------BYPASS control register input
	BYPASS_EN,
//-----------BYPASS status det
	BYPASS_STATUS,
//-----------Console mode setting
	Com1_Console_mode_ctrl,
	Com2_Console_mode_ctrl,
//-----------ERROR signal output
	bp_vol_error,
	Com1_mode_error,
	Com2_mode_error
);

input 			Clk;
input			Clk_5ms;
input			nRst;
input			RS485_422_RE0_DET_FPGA;
input			RS485_DE0_ISO_DET_FPGA;
input			RS232_TX_EN0_DET_FPGA;
input			RS422_DE0_DET_FPGA;
input			RS485_422_RE1_DET_FPGA;
input			RS485_DE1_ISO_DET_FPGA;
input			RS232_TX_EN1_DET_FPGA;
input			RS422_DE1_DET_FPGA;
input			BP_VOL_OV;
input			BP_VOL_UV;
input			BYPASS_EN;
input	[1:0]	Com1_Console_mode_ctrl;
input	[1:0]	Com2_Console_mode_ctrl;
input			BP_VOLTAGE_DIODE_DET;



output	[2:0]	Com1_Console_mode_det;
output	[2:0]	Com2_Console_mode_det;
output			bp_vol_error;
output			Com1_mode_error;
output			Com2_mode_error;
output			BYPASS_STATUS;

reg     [2:0]	Com1_Console_mode_det;
reg     [2:0]	Com2_Console_mode_det;
reg 			last_Clk_5ms = 1'b0;

parameter		COM_CONSOLE_DELAY_NUM	= 2;

always @( posedge Clk )
begin
	last_Clk_5ms <= Clk_5ms;
end

//COM1 console mode det
reg		[1:0]	Com1_Console_mode_ctrl_temp1 = 2'b11;
reg		[1:0]	Com1_Console_mode_ctrl_temp2 = 2'b11;
reg				Com1_Console_mode_ctrl_delay = 1'b0;
reg		[1:0]	Com1_Console_mode_ctrl_delay_cnt = 2'b0;
reg				Com1_Console_mode_delay_flag;
reg				Com1_mode_error;

wire			Com1_Console_mode_ctrl_vary;
wire			Com1_work_at_rs232;
wire			Com1_work_at_rs485;
wire			Com1_work_at_rs422;
wire			Com1_work_at_forbid;


assign			Com1_Console_mode_ctrl_vary = (Com1_Console_mode_ctrl_temp1[1:0] == Com1_Console_mode_ctrl_temp2[1:0])? 1'b0 : 1'b1;
assign			Com1_work_at_rs232	= RS232_TX_EN0_DET_FPGA & !RS485_DE0_ISO_DET_FPGA & RS485_422_RE0_DET_FPGA & !RS422_DE0_DET_FPGA;
assign			Com1_work_at_rs485	= !RS232_TX_EN0_DET_FPGA & !RS422_DE0_DET_FPGA & ((RS485_422_RE0_DET_FPGA & RS485_DE0_ISO_DET_FPGA) || (!RS485_422_RE0_DET_FPGA & !RS485_DE0_ISO_DET_FPGA) );  
assign			Com1_work_at_rs422	= !RS232_TX_EN0_DET_FPGA & !RS485_DE0_ISO_DET_FPGA & !RS485_422_RE0_DET_FPGA & RS422_DE0_DET_FPGA;
assign			Com1_work_at_forbid = !RS232_TX_EN0_DET_FPGA & !RS485_DE0_ISO_DET_FPGA & RS485_422_RE0_DET_FPGA & !RS422_DE0_DET_FPGA;


always @( posedge Clk or negedge nRst)
begin
	if(!nRst)
		begin
			Com1_Console_mode_ctrl_temp1[1:0] <= 2'b11;
			Com1_Console_mode_ctrl_temp2[1:0] <= 2'b11;
		end
	else
		begin
			Com1_Console_mode_ctrl_temp1[1:0] <= Com1_Console_mode_ctrl[1:0];
			Com1_Console_mode_ctrl_temp2[1:0] <= Com1_Console_mode_ctrl_temp1[1:0];
		end
end


always @( posedge Clk or negedge nRst )
begin
	if(!nRst)
		begin
			Com1_Console_mode_ctrl_delay_cnt <= 2'b0;
			Com1_Console_mode_delay_flag	 <= 1'b0;
			Com1_mode_error		<= 1'b0 ;
			Com1_Console_mode_det	<= 3'b000;
		end
	else
		begin
			if( Com1_Console_mode_ctrl_delay_cnt == COM_CONSOLE_DELAY_NUM )
				begin
					case( Com1_Console_mode_ctrl[1:0] )
					2'b00:
						begin
							if( Com1_work_at_forbid == 1'b1 )
								begin
									Com1_Console_mode_det	<= 3'b000;
									Com1_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com1_Console_mode_delay_flag	<= 1'b0;
									Com1_mode_error		<= 1'b0 ;
								end
							else
								begin
									Com1_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com1_Console_mode_delay_flag	 <= 1'b0;
									Com1_mode_error		<= 1'b1 ;
									Com1_Console_mode_det	<= 3'b100;
								end
						end
					2'b01:
						begin
							if( Com1_work_at_rs232 == 1'b1 )
								begin
									Com1_Console_mode_det	<= 3'b001;
									Com1_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com1_Console_mode_delay_flag	<= 1'b0;
									Com1_mode_error		<= 1'b0 ;
								end
							else
								begin
									Com1_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com1_Console_mode_delay_flag	 <= 1'b0;
									Com1_mode_error		<= 1'b1 ;
									Com1_Console_mode_det	<= 3'b100;
								end
						end
					2'b10:
						begin
							if( Com1_work_at_rs485 == 1'b1 )
								begin
									Com1_Console_mode_det	<= 3'b010;
									Com1_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com1_Console_mode_delay_flag	<= 1'b0;
									Com1_mode_error		<= 1'b0 ;
								end
							else
								begin
									Com1_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com1_Console_mode_delay_flag	 <= 1'b0;
									Com1_mode_error		<= 1'b1 ;
									Com1_Console_mode_det	<= 3'b100;
								end
						end
					2'b11:
						begin
							if( Com1_work_at_rs422 == 1'b1 )
								begin
									Com1_Console_mode_det	<= 3'b011;
									Com1_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com1_Console_mode_delay_flag	<= 1'b0;
									Com1_mode_error		<= 1'b0 ;
								end
							else
								begin
									Com1_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com1_Console_mode_delay_flag	 <= 1'b0;
									Com1_mode_error		<= 1'b1 ;
									Com1_Console_mode_det	<= 3'b100;
								end
						end	
					endcase
				end
			else
				begin 
					if( Com1_Console_mode_ctrl_vary == 1'b1 )
						begin
							Com1_Console_mode_delay_flag <= 1'b1;
							Com1_Console_mode_ctrl_delay_cnt <= 2'b0;						
						end
					else
						begin
							if( Com1_Console_mode_delay_flag & !last_Clk_5ms & Clk_5ms)
								begin
									Com1_Console_mode_ctrl_delay_cnt <= Com1_Console_mode_ctrl_delay_cnt + 1'b1;
								end
							else
								begin
									Com1_Console_mode_ctrl_delay_cnt <= Com1_Console_mode_ctrl_delay_cnt;
								end
						
						end
				end
		end
end

//COM2 console mode det
reg		[1:0]	Com2_Console_mode_ctrl_temp1 = 2'b11;
reg		[1:0]	Com2_Console_mode_ctrl_temp2 = 2'b11;
reg				Com2_Console_mode_ctrl_delay = 1'b0;
reg		[1:0]	Com2_Console_mode_ctrl_delay_cnt = 2'b0;
reg				Com2_Console_mode_delay_flag;
reg				Com2_mode_error;



wire			Com2_Console_mode_ctrl_vary;
wire			Com2_work_at_rs232;
wire			Com2_work_at_rs485;
wire			Com2_work_at_rs422;
wire			Com2_work_at_forbid;


assign			Com2_Console_mode_ctrl_vary = ( Com2_Console_mode_ctrl_temp1[1:0] == Com2_Console_mode_ctrl_temp2[1:0] )? 1'b0 : 1'b1;
assign			Com2_work_at_rs232	= RS232_TX_EN1_DET_FPGA & !RS485_DE1_ISO_DET_FPGA & RS485_422_RE1_DET_FPGA & !RS422_DE1_DET_FPGA;
assign			Com2_work_at_rs485	= !RS232_TX_EN1_DET_FPGA & !RS422_DE1_DET_FPGA  & ((RS485_422_RE1_DET_FPGA & RS485_DE1_ISO_DET_FPGA) || (!RS485_422_RE1_DET_FPGA & !RS485_DE1_ISO_DET_FPGA) );  
assign			Com2_work_at_rs422	= !RS232_TX_EN1_DET_FPGA & !RS485_DE1_ISO_DET_FPGA & !RS485_422_RE1_DET_FPGA & RS422_DE1_DET_FPGA;
assign			Com2_work_at_forbid = !RS232_TX_EN1_DET_FPGA & !RS485_DE1_ISO_DET_FPGA & RS485_422_RE1_DET_FPGA & !RS422_DE1_DET_FPGA;


always @( posedge Clk or negedge nRst)
begin
	if(!nRst)
		begin
			Com2_Console_mode_ctrl_temp1[1:0] <= 2'b11;
			Com2_Console_mode_ctrl_temp2[1:0] <= 2'b11;
		end
	else
		begin
			Com2_Console_mode_ctrl_temp1[1:0] <= Com2_Console_mode_ctrl[1:0];
			Com2_Console_mode_ctrl_temp2[1:0] <= Com2_Console_mode_ctrl_temp1[1:0];
		end
end


always @( posedge Clk or negedge nRst )
begin
	if(!nRst)
		begin
			Com2_Console_mode_ctrl_delay_cnt <= 2'b0;
			Com2_Console_mode_delay_flag	 <= 1'b0;
			Com2_mode_error		<= 1'b0 ;
			Com2_Console_mode_det	<= 3'b000;
		end
	else
		begin
			if( Com2_Console_mode_ctrl_delay_cnt == COM_CONSOLE_DELAY_NUM )
				begin
					case( Com2_Console_mode_ctrl[1:0] )
					2'b00:
						begin
							if( Com2_work_at_forbid == 1'b1 )
								begin
									Com2_Console_mode_det	<= 3'b000;
									Com2_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com2_Console_mode_delay_flag	<= 1'b0;
									Com2_mode_error		<= 1'b0 ;
								end
							else
								begin
									Com2_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com2_Console_mode_delay_flag	 <= 1'b0;
									Com2_mode_error		<= 1'b1 ;
									Com2_Console_mode_det	<= 3'b100;
								end
						end
					2'b01:
						begin
							if( Com2_work_at_rs232 == 1'b1 )
								begin
									Com2_Console_mode_det	<= 3'b001;
									Com2_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com2_Console_mode_delay_flag	<= 1'b0;
									Com2_mode_error		<= 1'b0 ;
								end
							else
								begin
									Com2_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com2_Console_mode_delay_flag	 <= 1'b0;
									Com2_mode_error		<= 1'b1 ;
									Com2_Console_mode_det	<= 3'b100;
								end
						end
					2'b10:
						begin
							if( Com2_work_at_rs485 == 1'b1 )
								begin
									Com2_Console_mode_det	<= 3'b010;
									Com2_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com2_Console_mode_delay_flag	<= 1'b0;
									Com2_mode_error		<= 1'b0 ;
								end
							else
								begin
									Com2_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com2_Console_mode_delay_flag	 <= 1'b0;
									Com2_mode_error		<= 1'b1 ;
									Com2_Console_mode_det	<= 3'b100;
								end
						end
					2'b11:
						begin
							if( Com2_work_at_rs422 == 1'b1 )
								begin
									Com2_Console_mode_det	<= 3'b011;
									Com2_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com2_Console_mode_delay_flag	<= 1'b0;
									Com2_mode_error		<= 1'b0 ;
								end
							else
								begin
									Com2_Console_mode_ctrl_delay_cnt <= 2'b0;
									Com2_Console_mode_delay_flag	 <= 1'b0;
									Com2_mode_error		<= 1'b1 ;
									Com2_Console_mode_det	<= 3'b100;
								end
						end	
					endcase
				end
			else
				begin 
					if( Com2_Console_mode_ctrl_vary == 1'b1 )
						begin
							Com2_Console_mode_delay_flag <= 1'b1;
							Com2_Console_mode_ctrl_delay_cnt <= 2'b0;
						end
					else
						begin
							if( Com2_Console_mode_delay_flag == 1'b1 & !last_Clk_5ms & Clk_5ms )
								begin
									Com2_Console_mode_ctrl_delay_cnt <= Com2_Console_mode_ctrl_delay_cnt + 1'b1;
								end
							else
								begin
									Com2_Console_mode_ctrl_delay_cnt <= Com2_Console_mode_ctrl_delay_cnt;
								end
						
						end
				end
		end
end

//-------------------BYPASS voltage detect-------------------
reg 		bypass_en_temp1;
reg			bypass_en_temp2;
reg	 [4:0]	bypass_on_delay_cnt;
reg	 [4:0]	bypass_off_delay_cnt;
reg			bypass_off_delay_flag;
reg			bypass_on_delay_flag;
reg			bypass_off_voltage_cmp_flag;
reg         bypass_on_voltage_cmp_flag;
reg			BYPASS_STATUS;  

wire		bypass_en_posedge;
wire		bypass_en_negative;

wire		BP_VOL_OV;
wire		BP_VOL_UV;

parameter   BYPASS_EN_DELAY_NUM = 20;

assign		bypass_en_posedge = bypass_en_temp1 & !bypass_en_temp2;
assign		bypass_en_negative = !bypass_en_temp1 & bypass_en_temp2;


always @( posedge Clk or negedge nRst )
begin
	if( !nRst )
		begin
			bypass_en_temp1 <= 1'b0;
			bypass_en_temp2 <= 1'b0;
		end
	else
		begin
			bypass_en_temp1 <= BYPASS_EN;
			bypass_en_temp2 <= bypass_en_temp1;
		end
end

//------------if bypass off, detect voltage after delay 20ms------
always @( posedge Clk or negedge nRst)
begin
	if(!nRst)
		begin
			bypass_off_delay_cnt <= 5'b0;
			bypass_off_voltage_cmp_flag <= 1'b0;
			bypass_off_delay_flag <= 1'b0;
		end
	else
		begin
			if( bypass_off_delay_cnt == BYPASS_EN_DELAY_NUM )
				begin
					bypass_off_voltage_cmp_flag <= 1'b1;
					bypass_off_delay_flag <= 1'b0;
					bypass_off_delay_cnt  <= 5'b0;
				end
			else
				begin
					if( bypass_en_negative == 1'b1)     //bypass on to off
						begin
							bypass_off_delay_flag <= 1'b1;
							bypass_off_voltage_cmp_flag <= 1'b0;
							bypass_off_delay_cnt <= 5'b0;
						end
					else
						if( bypass_en_posedge == 1'b1 )
							begin
								bypass_off_delay_flag <= 1'b0;
								bypass_off_voltage_cmp_flag <= 1'b0;
								bypass_off_delay_cnt <= 5'b0;
							end
						else						
							if( bypass_off_delay_flag & !last_Clk_5ms & Clk_5ms )
								begin
									bypass_off_delay_cnt <= bypass_off_delay_cnt + 1'b1;
								end
							else
								begin
									bypass_off_delay_cnt <= bypass_off_delay_cnt;
								end				
				end
		end
end

//------------if bypass on, detect voltage after delay 20ms------
reg					bp_vol_error;


always @( posedge Clk or negedge nRst)
begin
	if(!nRst)
		begin
			bypass_on_delay_cnt <= 5'b0;
			bypass_on_voltage_cmp_flag <= 1'b0;
			bypass_on_delay_flag <= 1'b0;
		end
	else
		begin
			if( bypass_on_delay_cnt == BYPASS_EN_DELAY_NUM )
				begin
					bypass_on_voltage_cmp_flag <= 1'b1;
					bypass_on_delay_flag <= 1'b0;
					bypass_on_delay_cnt  <= 5'b0;
				end
			else
				begin
					if( bypass_en_posedge == 1'b1)
						begin
							bypass_on_delay_flag <= 1'b1;
							bypass_on_voltage_cmp_flag <= 1'b0;
							bypass_on_delay_cnt <= 5'b0;
						end
					else
						if( bypass_en_negative == 1'b1 )
							begin
								bypass_on_delay_flag <= 1'b0;
								bypass_on_voltage_cmp_flag <= 1'b0;
								bypass_on_delay_cnt <= 5'b0;
							end
						else
								if( bypass_on_delay_flag & !last_Clk_5ms & Clk_5ms )
									begin
										bypass_on_delay_cnt <= bypass_on_delay_cnt + 1'b1;
									end
								else
									begin
										bypass_on_delay_cnt <= bypass_on_delay_cnt;
									end
							
				end
		end
end

always @( posedge Clk or negedge nRst)
begin
	if(!nRst)
		begin
			bp_vol_error <= 1'b0;
		end
	else
		begin
		if( bypass_off_voltage_cmp_flag == 1'b1 )
			begin
				if( BP_VOL_UV & !BP_VOL_OV )
					begin
						bp_vol_error <= 1'b0;
					end
				else
					begin
						bp_vol_error <= 1'b1;
					end
			end
		else
			if ( bypass_on_voltage_cmp_flag == 1'b1 )
				begin
					if( BP_VOL_UV & BP_VOL_OV & BP_VOLTAGE_DIODE_DET )
						begin
							bp_vol_error <= 1'b0;
						end
					else
						begin
							bp_vol_error <= 1'b1;
						end
				end			
		end
end


always @( posedge Clk or negedge nRst)
begin
	if(!nRst)
		begin
			BYPASS_STATUS <= 1'b1;
		end
	else
		begin
			if( BP_VOLTAGE_DIODE_DET == 1'b1 )
				begin
					BYPASS_STATUS <= 1'b1;
				end
			else
				begin
					BYPASS_STATUS <= 1'b0;
				end
		end
end

endmodule